package com.jindouyun.provider.server;

import com.jindouyun.provider.handler.RpcServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;

/**
 * @className: com.jindouyun.provider.server.RpcServer
 * @description: 基于Netty实现的RPC服务端
 * @author: tong.li
 * @createTime: 2021/10/12 20:43
 * @copyright: Tongcheng-Elong Holdings Limited
 */
@Component
public class RpcServer {

    private static final  Logger log = LoggerFactory.getLogger(RpcServer.class);

   private NioEventLoopGroup boosGroup = null;

   private NioEventLoopGroup workerGroup = null;

   @Resource
   private RpcServerHandler rpcServerHandler;

    /**
     * Netty服务端启动逻辑
     */
    public void start(String host, int port) {
        try {
            // 创建EventLoopGroup实例，默认线程数=CPU核心线程数*2
            boosGroup = new NioEventLoopGroup(1);
            workerGroup = new NioEventLoopGroup();
            // 创建Netty服务端,设置启动参数
            ChannelFuture server = new ServerBootstrap()
                    .group(boosGroup, workerGroup)
                    .channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            // 添加字符串编解码器，我们采用字符串序列化方式进行RPC传输，
                            ch.pipeline().addLast(new StringDecoder()).addLast(new StringEncoder())
                                    // 添加自定义的处理器
                                    .addLast(rpcServerHandler);
                        }
                    })
                    // 绑定IP和端口号
                    .bind(host, port)
                    // 监听Channel，关闭Channel
                    .sync();
            log.info(String.format("------------RPC服务器[%s:%s]端启动成功------------",host,port));
            server.channel().closeFuture().sync();
        } catch (Exception e) {
            log.error("RPC服务器启动失败",e);
            this.close();
        }
    }

    /**
     * 关闭资源
     */
    public void close(){
        if (boosGroup != null) {
            boosGroup.shutdownGracefully();
        }
        if (workerGroup != null) {
            workerGroup.shutdownGracefully();
        }
    }



}
